home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 11
/
Cream of the Crop 11-2.iso
/
os2
/
rsynth1.zip
/
holmes.c
< prev
next >
Wrap
Text File
|
1995-12-19
|
11KB
|
469 lines
#include <config.h>
/* $Id: holmes.c,v 1.13 1994/11/08 13:30:50 a904209 Exp a904209 $
*/
char *holmes_id = "$Id: holmes.c,v 1.13 1994/11/08 13:30:50 a904209 Exp a904209 $";
#include <stdio.h>
#include <ctype.h>
#include <useconfig.h>
#include <math.h>
#include "proto.h"
#include "nsynth.h"
#include "elements.h"
#include "darray.h"
#include "holmes.h"
#include "phfeat.h"
#include "getargs.h"
#if 1
#define AMP_ADJ 14
#else
#define AMP_ADJ 0
#endif
FILE *par_file;
FILE *jsru_file;
int speed = 1;
double frac = 1.0;
typedef struct
{
float v; /* boundary value */
int t; /* transition time */
}
slope_t;
typedef struct
{
slope_t p[nEparm];
}
trans_t;
typedef struct
{
float a;
float b;
float v;
}
filter_t, *filter_ptr;
static float filter PROTO((filter_ptr p, Float v));
static void jsru_save PROTO((double f0, float *tp));
static float
filter(p, v)
filter_ptr p;
Float v;
{
return p->v = (p->a * v + p->b * p->v);
}
/* 'a' is dominant element, 'b' is dominated
ext is flag to say to use external times from 'a' rather
than internal i.e. ext != 0 if 'a' is NOT current element.
*/
static void set_trans PROTO((slope_t * t, Elm_ptr a, Elm_ptr b, int ext, int e));
static void
set_trans(t, a, b, ext, e)
slope_t *t;
Elm_ptr a;
Elm_ptr b;
int ext;
int e;
{
int i;
for (i = 0; i < nEparm; i++)
{
t[i].t = ((ext) ? a->p[i].ed : a->p[i].id) * speed;
if (t[i].t)
t[i].v = a->p[i].fixd + (a->p[i].prop * b->p[i].stdy) * (float) 0.01;
else
t[i].v = b->p[i].stdy;
}
}
static float linear PROTO((Float a, Float b, int t, int d));
/*
______________ b
/
/
/
a____________/
0 d
---------------t---------------
*/
static float
linear(a, b, t, d)
Float a;
Float b;
int t;
int d;
{
if (t <= 0)
return a;
else if (t >= d)
return b;
else
{
float f = (float) t / (float) d;
return (a + (b - a) * f);
}
}
static float interpolate PROTO((char *w, char *p, slope_t * s, slope_t * e, Float mid, int t, int d));
static float
interpolate(w, p, s, e, mid, t, d)
char *w;
char *p;
slope_t *s;
slope_t *e;
Float mid;
int t;
int d;
{
float steady = d - (s->t + e->t);
#ifdef DEBUG
fprintf(stderr, "%4s %s s=%g,%d e=%g,%d m=%g,%g\n",
w, p, s->v, s->t, e->v, e->t, mid, steady);
#endif
if (steady >= 0)
{
/* Value reaches stready state somewhere ... */
if (t < s->t)
return linear(s->v, mid, t, s->t); /* initial transition */
else
{
t -= s->t;
if (t <= steady)
return mid; /* steady state */
else
return (linear(mid, e->v, (int) (t - steady), e->t));
/* final transition */
}
}
else
{
float f = (float) 1.0 - ((float) t / (float) d);
float sp = linear(s->v, mid, t, s->t);
float ep = linear(e->v, mid, d - t, e->t);
return (f * sp + ((float) 1.0 - f) * ep);
}
}
unsigned
holmes(nelm, elm, nsamp, samp_base)
unsigned nelm;
unsigned char *elm;
unsigned nsamp;
short *samp_base;
{
filter_t flt[nEparm];
klatt_frame_t pars;
short *samp = samp_base;
Elm_ptr le = &Elements[0];
unsigned i = 0;
unsigned tstress = 0;
unsigned ntstress = 0;
slope_t stress_s;
slope_t stress_e;
float top = 1.1 * def_pars.F0hz10;
int j;
pars = def_pars;
pars.FNPhz = le->p[fn].stdy;
pars.B1phz = pars.B1hz = 60;
pars.B2phz = pars.B2hz = 90;
pars.B3phz = pars.B3hz = 150;
#if 0
pars.F4hz = 3500;
#endif
pars.B4phz = def_pars.B4phz;
/* flag new utterance */
parwave_init(&klatt_global);
/* Set stress attack/decay slope */
stress_s.t = 40;
stress_e.t = 40;
stress_e.v = 0.0;
for (j = 0; j < nEparm; j++)
{
flt[j].v = le->p[j].stdy;
flt[j].a = frac;
flt[j].b = (float) 1.0 - (float) frac;
}
while (i < nelm)
{
Elm_ptr ce = &Elements[elm[i++]];
unsigned dur = elm[i++];
i++; /* skip stress */
/* Skip zero length elements which are only there to affect
boundary values of adjacent elements
*/
if (dur > 0)
{
Elm_ptr ne = (i < nelm) ? &Elements[elm[i]] : &Elements[0];
slope_t start[nEparm];
slope_t end[nEparm];
unsigned t;
if (ce->rk > le->rk)
{
if (par_file)
fprintf(par_file, "# %s < %s\n", le->name, ce->name);
set_trans(start, ce, le, 0, 's');
/* we dominate last */
}
else
{
if (par_file)
fprintf(par_file, "# %s >= %s\n", le->name, ce->name);
set_trans(start, le, ce, 1, 's');
/* last dominates us */
}
if (ne->rk > ce->rk)
{
if (par_file)
fprintf(par_file, "# %s < %s\n", ce->name, ne->name);
set_trans(end, ne, ce, 1, 'e');
/* next dominates us */
}
else
{
if (par_file)
fprintf(par_file, "# %s >= %s\n", ce->name, ne->name);
set_trans(end, ce, ne, 0, 'e');
/* we dominate next */
}
if (par_file)
{
int j;
fprintf(par_file, "# %s\n", ce->name);
for (j = 0; j < nEparm; j++)
fprintf(par_file, "%c%6s", (j) ? ' ' : '#', Ep_name[j]);
fprintf(par_file, "\n");
for (j = 0; j < nEparm; j++)
fprintf(par_file, "%c%6.4g", (j) ? ' ' : '#', start[j].v);
fprintf(par_file, "\n");
for (j = 0; j < nEparm; j++)
fprintf(par_file, "%c%6d", (j) ? ' ' : '#', start[j].t);
fprintf(par_file, "\n");
}
for (t = 0; t < dur; t++, tstress++)
{
float base = top * 0.8 ; /* 3 * top / 5 */
float tp[nEparm];
int j;
if (tstress == ntstress)
{
unsigned j = i;
stress_s = stress_e;
tstress = 0;
ntstress = dur;
#ifdef DEBUG_STRESS
printf("Stress %g -> ", stress_s.v);
#endif
while (j <= nelm)
{
Elm_ptr e = (j < nelm) ? &Elements[elm[j++]] : &Elements[0];
unsigned du = (j < nelm) ? elm[j++] : 0;
unsigned s = (j < nelm) ? elm[j++] : 3;
if (s || e->feat & vwl)
{
unsigned d = 0;
if (s)
stress_e.v = (float) s / 3;
else
stress_e.v = (float) 0.1;
do
{
d += du;
#ifdef DEBUG_STRESS
printf("%s", (e && e->dict) ? e->dict : "");
#endif
e = (j < nelm) ? &Elements[elm[j++]] : &Elements[0];
du = elm[j++];
}
while ((e->feat & vwl) && elm[j++] == s);
ntstress += d / 2;
break;
}
ntstress += du;
}
#ifdef DEBUG_STRESS
printf(" %g @ %d\n", stress_e.v, ntstress);
#endif
}
for (j = 0; j < nEparm; j++)
tp[j] = filter(flt + j, interpolate(ce->name, Ep_name[j], &start[j], &end[j], (float) ce->p[j].stdy, t, dur));
/* Now call the synth for each frame */
pars.F0hz10 = base + (top - base) *
interpolate("", "f0", &stress_s, &stress_e, (float) 0, tstress, ntstress);
pars.AVdb = pars.AVpdb = tp[av];
pars.AF = tp[af];
pars.FNZhz = tp[fn];
pars.ASP = tp[asp];
pars.Aturb = tp[avc];
pars.B1phz = pars.B1hz = tp[b1];
pars.B2phz = pars.B2hz = tp[b2];
pars.B3phz = pars.B3hz = tp[b3];
pars.F1hz = tp[f1];
pars.F2hz = tp[f2];
pars.F3hz = tp[f3];
/* AMP_ADJ + is a bodge to get amplitudes up to klatt-compatible levels
Needs to be fixed properly in tables
*/
/*
pars.ANP = AMP_ADJ + tp[an];
*/
pars.AB = AMP_ADJ + tp[ab];
pars.A5 = AMP_ADJ + tp[a5];
pars.A6 = AMP_ADJ + tp[a6];
pars.A1 = AMP_ADJ + tp[a1];
pars.A2 = AMP_ADJ + tp[a2];
pars.A3 = AMP_ADJ + tp[a3];
pars.A4 = AMP_ADJ + tp[a4];
parwave(&klatt_global, &pars, samp);
samp += klatt_global.nspfr;
if (par_file)
{
for (j = 0; j < nEparm; j++)
fprintf(par_file, " %6.4g", tp[j]);
fprintf(par_file, "\n");
}
if (jsru_file)
jsru_save(pars.F0hz10 * 0.1, tp);
/* Declination of f0 envelope 0.25Hz / cS */
/* top -= 0.5; */
}
if (par_file)
{
int j;
for (j = 0; j < nEparm; j++)
fprintf(par_file, "%c%6.4g", (j) ? ' ' : '#', end[j].v);
fprintf(par_file, "\n");
for (j = 0; j < nEparm; j++)
fprintf(par_file, "%c%6d", (j) ? ' ' : '#', end[j].t);
fprintf(par_file, "\n");
}
}
le = ce;
}
return (samp - samp_base);
}
int
init_holmes(argc, argv)
int argc;
char *argv[];
{
char *par_name = NULL;
char *jsru_name = NULL;
argc = getargs("Holmes",argc, argv,
"p", "", &par_name, "Parameter file for plot",
"j", "", &jsru_name, "Data for alternate synth (JSRU)",
"S", "%d", &speed, "Speed (1.0 is 'normal')",
"K", "%lg", &frac, "Parameter filter 'fraction'",
NULL);
if (help_only)
return argc;
if (par_name)
{
par_file = fopen(par_name, "w");
if (!par_file)
perror(par_name);
}
if (jsru_name)
{
jsru_file = fopen(jsru_name, "w");
if (!jsru_file)
perror(jsru_name);
}
return argc;
}
void
term_holmes()
{
if (par_file)
fclose(par_file);
if (jsru_file)
fclose(jsru_file);
}
static int jsru_freq PROTO((Float f, Float base, Float inc));
static int
jsru_freq(f, base, inc)
Float f;
Float base;
Float inc;
{
int i;
f = (f - base) / inc;
i = (int) f;
if (i >= 64)
i = 63;
return i;
}
static int jsru_amp PROTO((Float a));
static int
jsru_amp(a)
Float a;
{
int i = a;
if (i <= 0)
i = 1;
if (i >= 64)
i = 63;
return i;
}
/* 0 1 2 3 4 5
F1 F2 F3 FN
flflim 125.0 550.0 1350.0 3500.0 3500.0 95.0
fincrm 25.0 50.0 50.0 0.0 0.0 5.0
*/
static void
jsru_save(f0, tp)
double f0;
float *tp;
{
f0 = 16 * (log(f0 / 25.0) / log(2.0)) - 1;
/* fn, alf, f1, a1, f2, a2, f3, a3, ahf, v, f0, m */
fputc(jsru_freq(tp[fn], 95.0, 5.0), jsru_file);
fputc(jsru_amp(tp[an]), jsru_file);
fputc(jsru_freq(tp[f1], 125.0, 25.0), jsru_file);
fputc(jsru_amp(tp[a1]), jsru_file);
fputc(jsru_freq(tp[f2], 550.0, 50.0), jsru_file);
fputc(jsru_amp(tp[a2]), jsru_file);
fputc(jsru_freq(tp[f3], 1350.0, 50.0), jsru_file);
fputc(jsru_amp(tp[a3]), jsru_file);
fputc(jsru_amp(tp[a4]), jsru_file);
fputc(jsru_amp(tp[av]), jsru_file);
fputc((int) f0, jsru_file);
fputc((int) 32, jsru_file);
}